FOLLOW-UP – Add preamble to each MakeData script
Goals
Initialize metadata for the GRS analyses Identify individuals who are eligible for analysis based on having known Celiac status and no known first degree relatives in the analysis cohort
Load frequently used packages
library(openxlsx)
library(ggrepel)
library(dplyr)
library(tidyr)
library(data.table)
library(broom)
library(broomExtra)
library(tibble)
library(sjstats)
library(car)
library(lme4)
Loading required package: Matrix
Warning: package ‘Matrix’ was built under R version 4.1.2
Attaching package: ‘Matrix’
The following objects are masked from ‘package:tidyr’:
expand, pack, unpack
library(lmerTest)
Attaching package: ‘lmerTest’
The following object is masked from ‘package:lme4’:
lmer
The following object is masked from ‘package:stats’:
step
library(ggplot2)
library(tibble)
library(modelr)
library(tidyverse)
#library(miceadds)
library(ggforce)
require(openxlsx)
library(tidyverse)
library(caret)
library(glmnet)
Loaded glmnet 4.1-3
library(ggplot2)
select <- dplyr::select
filter <- dplyr::filter
Print session info for reproducibility
sessionInfo()
R version 4.1.1 (2021-08-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Catalina 10.15.7
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.1/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] grid stats graphics grDevices utils datasets methods base
other attached packages:
[1] glmnet_4.1-3 lmerTest_3.1-3 lme4_1.1-29 Matrix_1.4-1 scales_1.2.0
[6] IlluminaDataTestFiles_1.30.0 illuminaio_0.34.0 ComplexHeatmap_2.8.0 RColorBrewer_1.1-3 circlize_0.4.14
[11] lmPerm_2.1.0 MASS_7.3-56 gridExtra_2.3 caret_6.0-91 lattice_0.20-45
[16] ggforce_0.3.3 forcats_0.5.1 stringr_1.4.0 purrr_0.3.4 readr_2.1.2
[21] tidyverse_1.3.1 modelr_0.1.8 car_3.0-12 carData_3.0-5 sjstats_0.18.1
[26] tibble_3.1.6 broomExtra_4.3.2 broom_0.7.12 data.table_1.14.2 tidyr_1.2.0
[31] dplyr_1.0.8 ggrepel_0.9.1 ggplot2_3.3.5 openxlsx_4.2.5 skimr_2.1.3
loaded via a namespace (and not attached):
[1] readxl_1.4.0 backports_1.4.1 plyr_1.8.7 repr_1.1.4 splines_4.1.1 listenv_0.8.0 TH.data_1.1-0
[8] digest_0.6.29 foreach_1.5.2 htmltools_0.5.2 fansi_1.0.3 magrittr_2.0.3 cluster_2.1.3 doParallel_1.0.17
[15] tzdb_0.3.0 recipes_0.2.0 globals_0.14.0 gower_1.0.0 matrixStats_0.61.0 R.utils_2.11.0 sandwich_3.0-1
[22] askpass_1.1 hardhat_0.2.0 colorspace_2.0-3 rvest_1.0.2 haven_2.4.3 xfun_0.30 crayon_1.5.1
[29] jsonlite_1.8.0 survival_3.3-1 zoo_1.8-9 iterators_1.0.14 glue_1.6.2 polyclip_1.10-0 gtable_0.3.0
[36] ipred_0.9-12 emmeans_1.7.3 GetoptLong_1.0.5 sjmisc_2.8.9 future.apply_1.8.1 shape_1.4.6 BiocGenerics_0.38.0
[43] abind_1.4-5 mvtnorm_1.1-3 DBI_1.1.2 Rcpp_1.0.8.3 xtable_1.8-4 performance_0.9.0 clue_0.3-60
[50] bit_4.0.4 stats4_4.1.1 lava_1.6.10 prodlim_2019.11.13 datawizard_0.4.0 httr_1.4.2 ellipsis_0.3.2
[57] R.methodsS3_1.8.1 pkgconfig_2.0.3 farver_2.1.0 sass_0.4.1 nnet_7.3-17 dbplyr_2.1.1 utf8_1.2.2
[64] labeling_0.4.2 tidyselect_1.1.2 rlang_1.0.2 reshape2_1.4.4 effectsize_0.6.0.1 munsell_0.5.0 cellranger_1.1.0
[71] tools_4.1.1 cli_3.2.0 generics_0.1.2 sjlabelled_1.1.8 evaluate_0.15 fastmap_1.1.0 yaml_2.3.5
[78] bit64_4.0.5 ModelMetrics_1.2.2.2 knitr_1.38 fs_1.5.2 zip_2.2.0 future_1.24.0 nlme_3.1-157
[85] R.oo_1.24.0 xml2_1.3.3 compiler_4.1.1 rstudioapi_0.13 png_0.1-7 reprex_2.0.1 tweenr_1.0.2
[92] bslib_0.3.1 stringi_1.7.6 parameters_0.17.0 nloptr_2.0.0 vctrs_0.4.0 pillar_1.7.0 lifecycle_1.0.1
[99] jquerylib_0.1.4 GlobalOptions_0.1.2 estimability_1.3 insight_0.17.0 R6_2.5.1 IRanges_2.26.0 parallelly_1.30.0
[106] codetools_0.2-18 boot_1.3-28 assertthat_0.2.1 openssl_2.0.0 rjson_0.2.21 withr_2.5.0 S4Vectors_0.30.2
[113] multcomp_1.4-18 mgcv_1.8-40 bayestestR_0.11.5 parallel_4.1.1 hms_1.1.1 rpart_4.1.16 timeDate_3043.102
[120] base64_2.0 coda_0.19-4 class_7.3-20 minqa_1.2.4 rmarkdown_2.13 Cairo_1.5-15 pROC_1.18.0
[127] numDeriv_2016.8-1.1 lubridate_1.8.0 base64enc_0.1-3
Define in/out directory
dir <- "/Users/shawjes/Dropbox/EspinosaGroup/ANALYSIS/Celiac_MultiOmics/GRS/DSMIG_Shared/Manuscript_Figure1/Data"
Load MEGA to HTP ID key
setwd(dir)
Warning: The working directory was changed to /Users/shawjes/Dropbox/EspinosaGroup/ANALYSIS/Celiac_MultiOmics/GRS/DSMIG_Shared/Manuscript_Figure1/Data inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
MEGA.IDkey <- fread("MEGA_041822_MEGA2_to_HTP_ID_key_v0.1_JRS.csv")
MEGA.IDkey
Put the column names representing identifiers into a vector for reference below
ID_colnames <- c("FamilyID", "RecordID", "MEGA.FID", "MEGA.IID", "MEGA.LabID")
Define custom function for mode
# Create the function.
getmode <- function(v) {
uniqv <- unique(v)
uniqv[which.max(tabulate(match(v, uniqv)))]
}
Check that each individual was only genotyped one time
if( (meta.MEGA.T21_visit1_Celiac01 %>%
group_by(RecordID) %>%
summarise(N = n()) %>%
arrange(desc(N)) %>%
ungroup() %>%
summarise(var(N)) == 0) ) {"Great, all RecordIDs have the same number of rows of data."} else {
print("Oops, RecordIDs have varying number of rows.");
temp <- meta.MEGA.T21_visit1_Celiac01 %>%
group_by(RecordID) %>%
summarise(N_rows = n()) %>%
arrange(desc(N_rows)) %>%
ungroup() %>%
mutate(min.N_rows = min(N_rows),
max.N_rows = max(N_rows),
mode.N_rows = getmode(N_rows),
N_rows_Equal_mode = ifelse(N_rows == mode.N_rows, 1, 0),
N_rows_NotEqual_mode = ifelse(N_rows != mode.N_rows, 1, 0))
print(paste("N = ", sum(temp$N_rows_Equal_mode), " RecordIDs with N_rows = ", unique(temp$mode.N_rows), sep = ""))
print(paste("N = ", sum(temp$N_rows_NotEqual_mode),
" RecordIDs with mean N_rows = ",
mean((temp %>% filter(N_rows!=mode.N_rows))$N_rows),
"\nPrinting problematic RecordIDs now. Problems stored in `problems`",
sep = ""))
#print(paste("N = ", sum(temp$N_Equal_mode[1]), " samples with nrow = ", temp$N, sep = ""))
problems <- temp %>%
filter(N_rows != mode.N_rows) %>%
select(RecordID, N_rows, mode.N_rows) %>%
left_join(meta.MEGA.T21_visit1_Celiac01, by = "RecordID") %>%
select(FamilyID, RecordID, MEGA.IID, MEGA.LabID, N_rows, mode.N_rows) %>%
unique()
print(problems)
}
[1] "Oops, RecordIDs have varying number of rows."
[1] "N = 205 RecordIDs with N_rows = 1"
[1] "N = 5 RecordIDs with mean N_rows = 2\nPrinting problematic RecordIDs now. Problems stored in `problems`"
print("Based on this output, five samples were genotyped twice in different wells.")
[1] "Based on this output, five samples were genotyped twice in different wells."
print("Below we will clean the data to keep only the first sample well for each RecordID.")
[1] "Below we will clean the data to keep only the first sample well for each RecordID."
Since some RecordIDs/LabIDs were genotyped in more than one well, sort MEGA.IID alphabetically within RecordID and then keep the first MEGA.IID
Check if now each RecordID has only one MEGA.IID
print(paste("Rows in `mega_Snp_dosage.clean01` = ", meta.MEGA.T21_visit1_Celiac01 %>% select(RecordID, MEGA.IID) %>% unique() %>% nrow(), sep = ""))
[1] "Rows in `mega_Snp_dosage.clean01` = 215"
print(paste("Rows in `mega_Snp_dosage.clean02` = ", meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>% select(RecordID, MEGA.IID) %>% unique() %>% nrow(), sep = ""))
[1] "Rows in `mega_Snp_dosage.clean02` = 210"
if( (meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
group_by(RecordID) %>%
summarise(N = n()) %>%
arrange(desc(N)) %>%
ungroup() %>%
summarise(var(N)) == 0) ) {"Great, now all RecordIDs have the same number of rows of data."} else {
print("Oops, RecordIDs have varying number of rows.");
temp <- meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
group_by(RecordID) %>%
summarise(N_rows = n()) %>%
arrange(desc(N_rows)) %>%
ungroup() %>%
mutate(min.N_rows = min(N_rows),
max.N_rows = max(N_rows),
mode.N_rows = getmode(N_rows),
N_rows_Equal_mode = ifelse(N_rows == mode.N_rows, 1, 0),
N_rows_NotEqual_mode = ifelse(N_rows != mode.N_rows, 1, 0))
print(paste("N = ", sum(temp$N_rows_Equal_mode), " RecordIDs with N_rows = ", unique(temp$mode.N_rows), sep = ""))
print(paste("N = ", sum(temp$N_rows_NotEqual_mode),
" RecordIDs with mean N_rows = ",
mean((temp %>% filter(N_rows!=mode.N_rows))$N_rows),
"\nPrinting problematic RecordIDs now. Problems stored in `problems`",
sep = ""))
#print(paste("N = ", sum(temp$N_Equal_mode[1]), " samples with nrow = ", temp$N, sep = ""))
problems <- temp %>%
filter(N_rows != mode.N_rows) %>%
select(RecordID, N_rows, mode.N_rows) %>%
left_join(meta.MEGA.T21_visit1_Celiac02, by = "RecordID") %>%
select(FamilyID, RecordID, MEGA.IID, MEGA.LabID, N_rows, mode.N_rows) %>%
unique()
print(problems)
}
[1] "Great, now all RecordIDs have the same number of rows of data."
If all of the following equal the same number of rows, then this dataframe now represents genotyping only once per individual
meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
select(FamilyID, RecordID, MEGA.IID, MEGA.LabID) %>%
unique() %>%
nrow()
[1] 210
meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
select(RecordID, MEGA.IID, MEGA.LabID) %>%
unique() %>%
nrow()
[1] 210
meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
select(MEGA.IID, MEGA.LabID) %>%
unique() %>%
nrow()
[1] 210
meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
select(MEGA.LabID) %>%
unique() %>%
nrow()
[1] 210
meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
select(MEGA.IID) %>%
unique() %>%
nrow()
[1] 210
meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
select(RecordID) %>%
unique() %>%
nrow()
[1] 210
meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
select(FamilyID, RecordID, MEGA.IID) %>%
unique() %>%
nrow()
[1] 210
meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
select(FamilyID, RecordID) %>%
unique() %>%
nrow()
[1] 210
meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
select(RecordID, MEGA.IID) %>%
unique() %>%
nrow()
[1] 210
print("If all of the numbers printed above equal the same number of rows, then this dataframe now represents genotyping only once per individual.")
[1] "If all of the numbers printed above equal the same number of rows, then this dataframe now represents genotyping only once per individual."
print("Good.")
[1] "Good."
Final check that all RecordIDs now have only 1 MEGA.IID after using the EXCLUDE_from_analysis column to filter
meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
select(RecordID, MEGA.IID) %>%
unique() %>%
group_by(RecordID) %>%
summarise(N = n()) %>%
arrange(desc(N)) %>%
left_join(meta.MEGA.T21_visit1_Celiac02, by = "RecordID") %>%
filter(N > 1)
print("Good. All RecordIDs have only 1 MEGA.IID after applying the EXCLUDE_from_analysis filter.")
[1] "Good. All RecordIDs have only 1 MEGA.IID after applying the EXCLUDE_from_analysis filter."
Check for twins and other relateds
If there are relateds in the dataset after applying the EXCLUDE filter, first prioritize keeping Celiac cases, then randomly choose one IID per FamilyID to retain for analysis
meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
select(FamilyID, RecordID) %>% #, MEGA.IID, MEGA.LabID) %>%
unique() %>%
group_by(FamilyID) %>%
summarise(N_RecordIDs_per_FamilyID = n()) %>%
ungroup() %>%
arrange(desc(N_RecordIDs_per_FamilyID)) %>%
filter(N_RecordIDs_per_FamilyID > 1)
relateds <- meta.MEGA.T21_visit1_Celiac02 %>% filter(EXCLUDE_from_analysis == 0) %>%
select(FamilyID, RecordID) %>% #, MEGA.IID, MEGA.LabID) %>%
unique() %>%
group_by(FamilyID) %>%
summarise(N_RecordIDs_per_FamilyID = n()) %>%
ungroup() %>%
arrange(desc(N_RecordIDs_per_FamilyID)) %>%
filter(N_RecordIDs_per_FamilyID > 1) %>%
left_join(meta.MEGA.T21_visit1_Celiac02, by = "FamilyID") %>%
select(FamilyID, N_RecordIDs_per_FamilyID, RecordID, MEGA.IID, MEGA.LabID, EXCLUDE_from_analysis, Celiac, Sex, Age_at_visit1) %>%
unique() %>%
#left_join(meta_comorb.022021, by = c("FamilyID", "RecordID", "MEGA.LabID"="LabID")) %>%
group_by(FamilyID) %>%
arrange(desc(Celiac)) %>%
mutate(index_within_FamilyID = row_number()) %>%
ungroup() %>%
select(FamilyID, N_RecordIDs_per_FamilyID, index_within_FamilyID, Celiac, Sex, Age_at_visit1, everything()) %>%
arrange(FamilyID, index_within_FamilyID)
relateds
relateds %>%
select(FamilyID, index_within_FamilyID, EXCLUDE_from_analysis, Celiac, Sex) %>%
unique() %>%
group_by(FamilyID, Sex) %>%
summarise(N = n())
`summarise()` has grouped output by 'FamilyID'. You can override using the `.groups` argument.
print("Decision: From FamilyID F0348 (2 individuals), keep INVTH328HA9 because this person is a Celiac case.")
[1] "Decision: From FamilyID F0348 (2 individuals), keep INVTH328HA9 because this person is a Celiac case."
print("Note: All other familys have only males or only females, except for one family with 1 of each.")
[1] "Note: All other familys have only males or only females, except for one family with 1 of each."
print("Decision: Therefore, from all other FamilyIDs, randomly select one individual to remain in the analysis.")
[1] "Decision: Therefore, from all other FamilyIDs, randomly select one individual to remain in the analysis."
set.seed(1234) # Set seed for randomly shuffling rows
relateds_to_keep = relateds[sample(1:nrow(relateds)), ] %>%
group_by(FamilyID) %>%
mutate(random_index = row_number()) %>%
ungroup() %>%
mutate(Keep = ifelse(FamilyID == "F0348" & Celiac == 1, 1,
ifelse(FamilyID == "F0348" & Celiac == 0, 0,
ifelse(random_index == 1, 1, 0)))) %>%
select(FamilyID, RecordID, MEGA.IID, MEGA.LabID, N_RecordIDs_per_FamilyID, index_within_FamilyID, random_index, Keep, everything()) %>%
arrange(FamilyID, index_within_FamilyID) %>%
filter(Keep == 1)
relateds_to_keep
relateds_to_keep$MEGA.IID
[1] "WG1-DNA_F10_HTP0295A" "WG1-DNA_H05_HTP0262A" "WG3-DNA_C03_HTP0333A3" "WG2-DNA_G10_HTP0480A" "WG3-DNA_C05_HTP0432A" "WG3-DNA_F05_HTP0566A"
Update the EXCLUDE_from_analysis and EXCLUDE_reason columns to indicate which IIDs to exclude within multiple-IID FamilyIDs
meta.MEGA.T21_visit1_Celiac03 <- meta.MEGA.T21_visit1_Celiac02 %>%
select(FamilyID, RecordID) %>% #, MEGA.IID, MEGA.LabID) %>%
unique() %>%
group_by(FamilyID) %>%
mutate(N_RecordIDs_per_FamilyID = n()) %>%
ungroup() %>%
arrange(desc(N_RecordIDs_per_FamilyID)) %>%
mutate(Multi_IID_FamilyID = ifelse(N_RecordIDs_per_FamilyID > 1, 1, 0)) %>%
left_join(meta.MEGA.T21_visit1_Celiac02, by = c("FamilyID", "RecordID")) %>%
mutate(Keep_from_Multi_IID_FamilyID = ifelse(MEGA.IID %in% relateds_to_keep$MEGA.IID, 1, 0)) %>%
mutate(EXCLUDE_reason = gsub("[.]", "", EXCLUDE_reason)) %>%
#filter(Multi_IID_FamilyID==1) %>% select(FamilyID, RecordID, N_RecordIDs_per_FamilyID, MEGA.IID, Keep_from_Multi_IID_FamilyID) %>% unique() %>% arrange(FamilyID, desc(Keep_from_Multi_IID_FamilyID))
mutate(EXCLUDE_from_analysis = ifelse(Multi_IID_FamilyID == 1 & Keep_from_Multi_IID_FamilyID == 0, 1, EXCLUDE_from_analysis),
EXCLUDE_reason = ifelse(is.na(EXCLUDE_reason) & Multi_IID_FamilyID == 1 & EXCLUDE_from_analysis == 1, "FamilyID with multiple RecordIDs",
ifelse(!is.na(EXCLUDE_reason) &
Multi_IID_FamilyID == 1 &
EXCLUDE_from_analysis == 1,
paste(EXCLUDE_reason, "; FamilyID with multiple RecordIDs", sep = ""), EXCLUDE_reason))) %>%
select(-c(Keep_from_Multi_IID_FamilyID)) %>%
rename(N_T21_RecordIDs_in_FamilyID = N_RecordIDs_per_FamilyID) %>%
select(FamilyID, RecordID, MEGA.FID, MEGA.IID, MEGA.LabID, Multi_IID_FamilyID, N_T21_RecordIDs_in_FamilyID, everything()) #%>%
#mutate(EXCLUDE_from_analysis = ifelse(is.na(EXCLUDE_from_analysis), 0, EXCLUDE_from_analysis))
meta.MEGA.T21_visit1_Celiac03
meta.MEGA.T21_visit1_Celiac03 %>%
select(FamilyID, RecordID, MEGA.FID, MEGA.IID, MEGA.LabID,
Multi_IID_FamilyID, N_T21_RecordIDs_in_FamilyID, Celiac, EXCLUDE_from_analysis, EXCLUDE_reason) %>%
unique() %>%
arrange(desc(Celiac), desc(EXCLUDE_from_analysis))
Verify that the EXCLUDE variable is working correctly
Not excluding any Celiac cases unless they represent a RecordID genotyped twice on MEGA. Producing a dataset with only one MEGA.IID per RecordID. Producing a dataset with only one RecordID per FamilyID.
meta.MEGA.T21_visit1_Celiac03 %>%
select(MEGA.IID, MEGA.LabID, Celiac, EXCLUDE_from_analysis, EXCLUDE_reason) %>%
unique() %>%
group_by(Celiac, EXCLUDE_from_analysis, EXCLUDE_reason) %>%
summarise(N = n())
`summarise()` has grouped output by 'Celiac', 'EXCLUDE_from_analysis'. You can override using the `.groups` argument.
print("Good, not excluding any Celiac cases unless they represent a RecordID genotyped twice on MEGA.")
[1] "Good, not excluding any Celiac cases unless they represent a RecordID genotyped twice on MEGA."
print("Reasons we are currently excluding IIDs represented in the plink *.fam are:
1) If the IID is for a RecordID that got genotyped twice, or
2) If the IID is from a FamilyID with multiple genotyped individuals.")
[1] "Reasons we are currently excluding IIDs represented in the plink *.fam are:\n 1) If the IID is for a RecordID that got genotyped twice, or\n 2) If the IID is from a FamilyID with multiple genotyped individuals."
meta.MEGA.T21_visit1_Celiac03 %>%
filter(EXCLUDE_from_analysis == 0) %>%
select(RecordID, MEGA.IID) %>%
unique() %>%
group_by(RecordID) %>%
summarise(N = n()) %>%
arrange(desc(N))
print("Good, only one MEGA.IID per RecordID.")
[1] "Good, only one MEGA.IID per RecordID."
meta.MEGA.T21_visit1_Celiac03 %>%
#filter(EXCLUDE_from_analysis == 0) %>%
select(FamilyID, RecordID, MEGA.IID) %>%
unique() %>%
group_by(FamilyID, RecordID, MEGA.IID) %>%
summarise(N = n()) %>%
arrange(desc(N))
`summarise()` has grouped output by 'FamilyID', 'RecordID'. You can override using the `.groups` argument.
print("Good, only one RecordID per FamilyID.")
[1] "Good, only one RecordID per FamilyID."
View who is being excluded at this stage and why
meta.MEGA.T21_visit1_Celiac03 %>%
select(FamilyID, RecordID, MEGA.FID, MEGA.IID, MEGA.LabID, Celiac, EXCLUDE_from_analysis, EXCLUDE_reason) %>%
unique() %>%
group_by(EXCLUDE_from_analysis, EXCLUDE_reason, Celiac) %>%
summarise(N = n())
`summarise()` has grouped output by 'EXCLUDE_from_analysis', 'EXCLUDE_reason'. You can override using the `.groups` argument.
meta.MEGA.T21_visit1_Celiac03 %>%
select(FamilyID, RecordID, MEGA.FID, MEGA.IID, MEGA.LabID, EXCLUDE_from_analysis, EXCLUDE_reason, Karyotype, Celiac, Sex) %>%
unique() %>%
group_by(EXCLUDE_from_analysis, EXCLUDE_reason, Karyotype, Celiac, Sex) %>%
summarise(N = n()) %>%
ungroup() %>%
#filter(#EXCLUDE_from_analysis == 0 &
# !is.na(Celiac)) %>%
mutate(Total = sum(N),
Pct = round(100*N/Total, digits = 2)) %>%
mutate(`N (%)` = paste(N, " (", Pct, ")", sep = "")) %>%
select(EXCLUDE_from_analysis, EXCLUDE_reason, Karyotype, Celiac, Sex, `N (%)`) %>%
mutate(Group = ifelse(Celiac == 0, "T21 without CD",
ifelse(Celiac == 1, "T21 with CD", NA))) %>%
select(EXCLUDE_from_analysis, EXCLUDE_reason, Group, Sex, `N (%)`)
`summarise()` has grouped output by 'EXCLUDE_from_analysis', 'EXCLUDE_reason', 'Karyotype', 'Celiac'. You can override using the `.groups` argument.
Save to files
setwd(dir)
Warning: The working directory was changed to /Users/shawjes/Dropbox/EspinosaGroup/ANALYSIS/Celiac_MultiOmics/GRS/DSMIG_Shared/Manuscript_Figure1/Data inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
fwrite(meta.MEGA.T21_visit1_Celiac03, "MEGA_041822_META_CeliacGRS_v0.1_JRS.csv")
fwrite(meta.MEGA.T21_visit1_Celiac03, "MEGA_041822_META_CeliacGRS_v0.1_JRS.tsv", sep = "\t")
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBGT0xMT1ctVVAgLS0gQWRkIHByZWFtYmxlIHRvIGVhY2ggTWFrZURhdGEgc2NyaXB0CiMjIyMgR29hbHMKSW5pdGlhbGl6ZSBtZXRhZGF0YSBmb3IgdGhlIEdSUyBhbmFseXNlcwpJZGVudGlmeSBpbmRpdmlkdWFscyB3aG8gYXJlIGVsaWdpYmxlIGZvciBhbmFseXNpcyBiYXNlZCBvbiBoYXZpbmcga25vd24gQ2VsaWFjIHN0YXR1cyBhbmQgbm8ga25vd24gZmlyc3QgZGVncmVlIHJlbGF0aXZlcyBpbiB0aGUgYW5hbHlzaXMgY29ob3J0CgojIyMjIExvYWQgZnJlcXVlbnRseSB1c2VkIHBhY2thZ2VzCmBgYHtyfQpsaWJyYXJ5KG9wZW54bHN4KQpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShicm9vbSkKbGlicmFyeShicm9vbUV4dHJhKQpsaWJyYXJ5KHRpYmJsZSkKbGlicmFyeShzanN0YXRzKQpsaWJyYXJ5KGNhcikKbGlicmFyeShsbWU0KQpsaWJyYXJ5KGxtZXJUZXN0KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodGliYmxlKQpsaWJyYXJ5KG1vZGVscikKbGlicmFyeSh0aWR5dmVyc2UpCiNsaWJyYXJ5KG1pY2VhZGRzKQpsaWJyYXJ5KGdnZm9yY2UpCnJlcXVpcmUob3Blbnhsc3gpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGNhcmV0KQpsaWJyYXJ5KGdsbW5ldCkKbGlicmFyeShnZ3Bsb3QyKQpzZWxlY3QgPC0gZHBseXI6OnNlbGVjdApmaWx0ZXIgPC0gZHBseXI6OmZpbHRlcgpgYGAKCiMjIyMgUHJpbnQgc2Vzc2lvbiBpbmZvIGZvciByZXByb2R1Y2liaWxpdHkKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCgojIyMjIERlZmluZSBpbi9vdXQgZGlyZWN0b3J5CmBgYHtyfQpkaXIgPC0gIi9Vc2Vycy9zaGF3amVzL0Ryb3Bib3gvRXNwaW5vc2FHcm91cC9BTkFMWVNJUy9DZWxpYWNfTXVsdGlPbWljcy9HUlMvRFNNSUdfU2hhcmVkL01hbnVzY3JpcHRfRmlndXJlMS9EYXRhIgpgYGAKCiMjIyMgTG9hZCBNRUdBIHRvIEhUUCBJRCBrZXkKYGBge3J9CnNldHdkKGRpcikKTUVHQS5JRGtleSA8LSBmcmVhZCgiTUVHQV8wNDE4MjJfTUVHQTJfdG9fSFRQX0lEX2tleV92MC4xX0pSUy5jc3YiKQoKTUVHQS5JRGtleQpgYGAKCiMjIyMgUmVhZCBpbiBsYXRlc3QgdmVyc2lvbiBvZiB0aGUgbWV0YS9jb21vcmIgZGF0YQpgYGB7cn0Kc2V0d2QoIi9Vc2Vycy9zaGF3amVzL0Ryb3Bib3gvRXNwaW5vc2FHcm91cC9EQVRBX01BSU4vTUVUQS9PbmVEcml2ZV8xXzItMTctMjAyMiIpCm1ldGFfY29tb3JiLjAyMjAyMSA8LSBmcmVhZCgiSFRQX0NMRUFORURfMDJfMjAyMV92MC41X0NPTU9SQl9NQVNURVJfUmVjb3JkSURfdnNfTGFiSUQuTGFiZWxzLnRzdiIpICU+JQogIHNlbGVjdChGYW1pbHlJRCwgUmVjb3JkSUQsIExhYklELCBBZ2VfYXRfdmlzaXQsIFNleCwgS2FyeW90eXBlLCBldmVyeXRoaW5nKCkpICU+JQogIG11dGF0ZShDZWxpYWMgPSBhcy5udW1lcmljKGBDZWxpYWMgZGlzZWFzZWApKQoKbWV0YV9jb21vcmIuMDIyMDIxCmBgYAoKIyMjIyBQdXQgdGhlIGNvbHVtbiBuYW1lcyByZXByZXNlbnRpbmcgaWRlbnRpZmllcnMgaW50byBhIHZlY3RvciBmb3IgcmVmZXJlbmNlIGJlbG93CmBgYHtyfQpJRF9jb2xuYW1lcyA8LSBjKCJGYW1pbHlJRCIsICJSZWNvcmRJRCIsICJNRUdBLkZJRCIsICJNRUdBLklJRCIsICJNRUdBLkxhYklEIikKYGBgCgojIyMjIE1ha2Ugc3Vic2V0IG9mIG1ldGEvY29tb3JiIGRhdGFzZXQgc3BlY2lmaWMgdG8gVmlzaXQgMSBmb3IgVDIxcyB3aXRoIGNvbXBsZXRlIENlbGlhYyBzdGF0dXMKYGBge3J9Cm1ldGFfY29tb3JiLlQyMV92aXNpdDFfQ2VsaWFjIDwtIG1ldGFfY29tb3JiLjAyMjAyMSAlPiUKICBmaWx0ZXIoS2FyeW90eXBlID09ICJUMjEiICYKICAgICAgICAgICAhaXMubmEoTGFiSUQpICYgRXZlbnRfbmFtZSA9PSAiVmlzaXQgMSIgJiAjIEFzc3VtaW5nIHRoYXQgQ2VsaWFjIHN0YXR1cyBmb3IgSFRQIHdhcyBhc2NlcnRhaW5lZCBhcyBvZiBwYXJ0aWNpcGFudCB2aXNpdCAxCiAgICAgICAgICAgIWlzLm5hKGBDZWxpYWMgZGlzZWFzZWApKSAlPiUKICBzZWxlY3QoY29sbmFtZXMobWV0YV9jb21vcmIuMDIyMDIxKVsxOjE4XSwKICAgICAgICAgYENlbGlhYyBkaXNlYXNlYCwgQ2VsaWFjLAogICAgICAgICBldmVyeXRoaW5nKCkpICU+JQogIHJlbmFtZShBZ2VfYXRfdmlzaXQxID0gQWdlX2F0X3Zpc2l0KQoKbWV0YV9jb21vcmIuVDIxX3Zpc2l0MV9DZWxpYWMKYGBgCgojIyMjIE1ha2UgbWV0YS9jb21vcmIgZGF0YXNldCBzcGVjaWZpYyB0byB2aXNpdCAxIGZvciBUMjFzIHdpdGggY29tcGxldGUgQ2VsaWFjIHN0YXR1cyBhbmQgY29tcGxldGUgTUVHQSBnZW5vdHlwaW5nCmBgYHtyfQojY29sbmFtZXMoTUVHQS5JRGtleSkKI2NvbG5hbWVzKG1ldGFfY29tb3JiLjAyMjAyMSkKCm1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYyA8LSBNRUdBLklEa2V5ICU+JQogIGZpbHRlcihIVFBfcGFydGljaXBhbnQgPT0gIlllcyIpICU+JQogIHNlbGVjdCgtYyhIVFBfcGFydGljaXBhbnQpKSAlPiUKICBsZWZ0X2pvaW4obWV0YV9jb21vcmIuVDIxX3Zpc2l0MV9DZWxpYWMgJT4lIG11dGF0ZShJbl9UMjFjZWxpYWNfbWV0YWRhdGEgPSAxKSwKICAgICAgICAgICAgYnkgPSBjKCJGYW1pbHlJRCIsICJSZWNvcmRJRCIpKQojIE5vdGU6IEhlcmUgSSdtIGpvaW5pbmcgdG8gdGhlIG1ldGFkYXRhIGNvcnJlc3BvbmRpbmcgdG8gdmlzaXQgMSwgd2hlbiBDZWxpYWMgc3RhdHVzIHdhcyBkZXRlcm1pbmVkIGZvciB0aGUgcHVycG9zZXMgb2YgdGhlIHN0dWR5LiAKIyBGb3IgdGhpcyByZWFzb24gSSBhbSBub3QgaW5jbHVkaW5nIExhYklEIGFzIGEgam9pbiBieSB2YXJpYWJsZS4KCm1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYyAlPiUKICBncm91cF9ieShJbl9wbGlua19mYW0sIEluX1QyMWNlbGlhY19tZXRhZGF0YSkgJT4lCiAgc3VtbWFyaXNlKE4gPSBuKCkpCnByaW50KCI2IHBhcnRpY2lwYW50cyBoYXZlIGNvbXBsZXRlIGdlbm90eXBlIGRhdGEgYnV0IGluY29tcGxldGUgQ2VsaWFjIHN0YXR1cy4iKQoKbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDEgPC0gbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjICU+JQogIGZpbHRlcighaXMubmEoSW5fcGxpbmtfZmFtKSAmICFpcy5uYShJbl9UMjFjZWxpYWNfbWV0YWRhdGEpKSAlPiUKICBzZWxlY3QoLWMoSW5fcGxpbmtfZmFtLCBJbl9UMjFjZWxpYWNfbWV0YWRhdGEpKQoKbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDEKYGBgCgojIyMjIERlZmluZSBjdXN0b20gZnVuY3Rpb24gZm9yIG1vZGUKYGBge3J9CiMgQ3JlYXRlIHRoZSBmdW5jdGlvbi4KZ2V0bW9kZSA8LSBmdW5jdGlvbih2KSB7CiAgIHVuaXF2IDwtIHVuaXF1ZSh2KQogICB1bmlxdlt3aGljaC5tYXgodGFidWxhdGUobWF0Y2godiwgdW5pcXYpKSldCn0KYGBgCgojIyMjIENoZWNrIHRoYXQgZWFjaCBpbmRpdmlkdWFsIHdhcyBvbmx5IGdlbm90eXBlZCBvbmUgdGltZQpgYGB7cn0KaWYoIChtZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMSAlPiUKICAgICBncm91cF9ieShSZWNvcmRJRCkgJT4lCiAgICAgc3VtbWFyaXNlKE4gPSBuKCkpICU+JQogICAgIGFycmFuZ2UoZGVzYyhOKSkgJT4lCiAgICAgdW5ncm91cCgpICU+JQogICAgIHN1bW1hcmlzZSh2YXIoTikpID09IDApICkgeyJHcmVhdCwgYWxsIFJlY29yZElEcyBoYXZlIHRoZSBzYW1lIG51bWJlciBvZiByb3dzIG9mIGRhdGEuIn0gZWxzZSB7CiAgICAgICBwcmludCgiT29wcywgUmVjb3JkSURzIGhhdmUgdmFyeWluZyBudW1iZXIgb2Ygcm93cy4iKTsKICAgICAgIHRlbXAgPC0gbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDEgJT4lCiAgICAgICAgIGdyb3VwX2J5KFJlY29yZElEKSAlPiUKICAgICAgICAgc3VtbWFyaXNlKE5fcm93cyA9IG4oKSkgJT4lCiAgICAgICAgIGFycmFuZ2UoZGVzYyhOX3Jvd3MpKSAlPiUKICAgICAgICAgdW5ncm91cCgpICU+JQogICAgICAgICBtdXRhdGUobWluLk5fcm93cyA9IG1pbihOX3Jvd3MpLAogICAgICAgICAgICAgICAgbWF4Lk5fcm93cyA9IG1heChOX3Jvd3MpLAogICAgICAgICAgICAgICAgbW9kZS5OX3Jvd3MgPSBnZXRtb2RlKE5fcm93cyksCiAgICAgICAgICAgICAgICBOX3Jvd3NfRXF1YWxfbW9kZSA9IGlmZWxzZShOX3Jvd3MgPT0gbW9kZS5OX3Jvd3MsIDEsIDApLAogICAgICAgICAgICAgICAgTl9yb3dzX05vdEVxdWFsX21vZGUgPSBpZmVsc2UoTl9yb3dzICE9IG1vZGUuTl9yb3dzLCAxLCAwKSkKICAgICAgIHByaW50KHBhc3RlKCJOID0gIiwgc3VtKHRlbXAkTl9yb3dzX0VxdWFsX21vZGUpLCAiIFJlY29yZElEcyB3aXRoIE5fcm93cyA9ICIsIHVuaXF1ZSh0ZW1wJG1vZGUuTl9yb3dzKSwgc2VwID0gIiIpKQogICAgICAgcHJpbnQocGFzdGUoIk4gPSAiLCBzdW0odGVtcCROX3Jvd3NfTm90RXF1YWxfbW9kZSksCiAgICAgICAgICAgICAgICAgICAiIFJlY29yZElEcyB3aXRoIG1lYW4gTl9yb3dzID0gIiwKICAgICAgICAgICAgICAgICAgIG1lYW4oKHRlbXAgJT4lIGZpbHRlcihOX3Jvd3MhPW1vZGUuTl9yb3dzKSkkTl9yb3dzKSwKICAgICAgICAgICAgICAgICAgICJcblByaW50aW5nIHByb2JsZW1hdGljIFJlY29yZElEcyBub3cuIFByb2JsZW1zIHN0b3JlZCBpbiBgcHJvYmxlbXNgIiwKICAgICAgICAgICAgICAgICAgIHNlcCA9ICIiKSkKICAgICAgICNwcmludChwYXN0ZSgiTiA9ICIsIHN1bSh0ZW1wJE5fRXF1YWxfbW9kZVsxXSksICIgc2FtcGxlcyB3aXRoIG5yb3cgPSAiLCB0ZW1wJE4sIHNlcCA9ICIiKSkKICAgICAgIAogICAgICAgcHJvYmxlbXMgPC0gdGVtcCAlPiUKICAgICAgICAgZmlsdGVyKE5fcm93cyAhPSBtb2RlLk5fcm93cykgJT4lCiAgICAgICAgIHNlbGVjdChSZWNvcmRJRCwgTl9yb3dzLCBtb2RlLk5fcm93cykgJT4lCiAgICAgICAgIGxlZnRfam9pbihtZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMSwgYnkgPSAiUmVjb3JkSUQiKSAlPiUKICAgICAgICAgc2VsZWN0KEZhbWlseUlELCBSZWNvcmRJRCwgTUVHQS5JSUQsIE1FR0EuTGFiSUQsIE5fcm93cywgbW9kZS5OX3Jvd3MpICU+JQogICAgICAgICB1bmlxdWUoKQogICAgICAgCiAgICAgICBwcmludChwcm9ibGVtcykKICAgICB9CgpwcmludCgiQmFzZWQgb24gdGhpcyBvdXRwdXQsIGZpdmUgc2FtcGxlcyB3ZXJlIGdlbm90eXBlZCB0d2ljZSBpbiBkaWZmZXJlbnQgd2VsbHMuIikKcHJpbnQoIkJlbG93IHdlIHdpbGwgY2xlYW4gdGhlIGRhdGEgdG8ga2VlcCBvbmx5IHRoZSBmaXJzdCBzYW1wbGUgd2VsbCBmb3IgZWFjaCBSZWNvcmRJRC4iKQpgYGAKCiMjIyMgU2luY2Ugc29tZSBSZWNvcmRJRHMvTGFiSURzIHdlcmUgZ2Vub3R5cGVkIGluIG1vcmUgdGhhbiBvbmUgd2VsbCwgc29ydCBNRUdBLklJRCBhbHBoYWJldGljYWxseSB3aXRoaW4gUmVjb3JkSUQgYW5kIHRoZW4ga2VlcCB0aGUgZmlyc3QgTUVHQS5JSUQKYGBge3J9CiMgRk9MTE9XIFVQOiBEb3VibGUgY2hlY2sgaWYgdGhlIHBhcnRpY2lwYW50IGdlbm90eXBlZCB0d2ljZSBoYXMgY29tcGxldGUgZ2Vub3R5cGVzIGluIGJvdGggc2V0cyBvZiBnZW5vdHlwZXMuCgptZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMiA8LSBtZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMSAlPiUKICBzZWxlY3QoUmVjb3JkSUQsIE1FR0EuSUlEKSAlPiUKICB1bmlxdWUoKSAlPiUKICBncm91cF9ieShSZWNvcmRJRCkgJT4lCiAgYXJyYW5nZShNRUdBLklJRCkgJT4lCiAgbXV0YXRlKGluZGV4X01FR0EuSUlEX2Zvcl9SZWNvcmRJRCA9IHJvd19udW1iZXIoKSkgJT4lCiAgdW5ncm91cCgpICU+JQogICNhcnJhbmdlKGRlc2MoaW5kZXhfTUVHQS5JSURfZm9yX1JlY29yZElEKSkgJT4lCiAgZnVsbF9qb2luKG1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAxLCBieSA9IGMoIlJlY29yZElEIiwgIk1FR0EuSUlEIikpICU+JQogIG11dGF0ZShFWENMVURFX2Zyb21fYW5hbHlzaXMgPSBpZmVsc2UoaW5kZXhfTUVHQS5JSURfZm9yX1JlY29yZElEID4gMSwgMSwgMCksCiAgICAgICAgIEVYQ0xVREVfcmVhc29uID0gaWZlbHNlKEVYQ0xVREVfZnJvbV9hbmFseXNpcyA9PSAxICYgaW5kZXhfTUVHQS5JSURfZm9yX1JlY29yZElEID4xLCAiUmVjb3JkSUQgZ2Vub3R5cGVkIHR3aWNlLiIsIE5BKSkKCm1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAyICU+JQogIHNlbGVjdChGYW1pbHlJRCwgUmVjb3JkSUQsIE1FR0EuRklELCBNRUdBLklJRCwgTUVHQS5MYWJJRCwKICAgICAgICAgaW5kZXhfTUVHQS5JSURfZm9yX1JlY29yZElELCBFWENMVURFX2Zyb21fYW5hbHlzaXMsIEVYQ0xVREVfcmVhc29uLCBldmVyeXRoaW5nKCkpICU+JQogIGFycmFuZ2UoUmVjb3JkSUQsIGluZGV4X01FR0EuSUlEX2Zvcl9SZWNvcmRJRCkKYGBgCgojIyMjIENoZWNrIGlmIG5vdyBlYWNoIFJlY29yZElEIGhhcyBvbmx5IG9uZSBNRUdBLklJRApgYGB7cn0KcHJpbnQocGFzdGUoIlJvd3MgaW4gYG1lZ2FfU25wX2Rvc2FnZS5jbGVhbjAxYCA9ICIsIG1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAxICU+JSBzZWxlY3QoUmVjb3JkSUQsIE1FR0EuSUlEKSAlPiUgdW5pcXVlKCkgJT4lIG5yb3coKSwgc2VwID0gIiIpKQpwcmludChwYXN0ZSgiUm93cyBpbiBgbWVnYV9TbnBfZG9zYWdlLmNsZWFuMDJgID0gIiwgbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDIgJT4lIGZpbHRlcihFWENMVURFX2Zyb21fYW5hbHlzaXMgPT0gMCkgJT4lIHNlbGVjdChSZWNvcmRJRCwgTUVHQS5JSUQpICU+JSB1bmlxdWUoKSAlPiUgbnJvdygpLCBzZXAgPSAiIikpCgppZiggKG1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAyICU+JSBmaWx0ZXIoRVhDTFVERV9mcm9tX2FuYWx5c2lzID09IDApICU+JQogICAgIGdyb3VwX2J5KFJlY29yZElEKSAlPiUKICAgICBzdW1tYXJpc2UoTiA9IG4oKSkgJT4lCiAgICAgYXJyYW5nZShkZXNjKE4pKSAlPiUKICAgICB1bmdyb3VwKCkgJT4lCiAgICAgc3VtbWFyaXNlKHZhcihOKSkgPT0gMCkgKSB7IkdyZWF0LCBub3cgYWxsIFJlY29yZElEcyBoYXZlIHRoZSBzYW1lIG51bWJlciBvZiByb3dzIG9mIGRhdGEuIn0gZWxzZSB7CiAgICAgICBwcmludCgiT29wcywgUmVjb3JkSURzIGhhdmUgdmFyeWluZyBudW1iZXIgb2Ygcm93cy4iKTsKICAgICAgIHRlbXAgPC0gbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDIgJT4lIGZpbHRlcihFWENMVURFX2Zyb21fYW5hbHlzaXMgPT0gMCkgJT4lCiAgICAgICAgIGdyb3VwX2J5KFJlY29yZElEKSAlPiUKICAgICAgICAgc3VtbWFyaXNlKE5fcm93cyA9IG4oKSkgJT4lCiAgICAgICAgIGFycmFuZ2UoZGVzYyhOX3Jvd3MpKSAlPiUKICAgICAgICAgdW5ncm91cCgpICU+JQogICAgICAgICBtdXRhdGUobWluLk5fcm93cyA9IG1pbihOX3Jvd3MpLAogICAgICAgICAgICAgICAgbWF4Lk5fcm93cyA9IG1heChOX3Jvd3MpLAogICAgICAgICAgICAgICAgbW9kZS5OX3Jvd3MgPSBnZXRtb2RlKE5fcm93cyksCiAgICAgICAgICAgICAgICBOX3Jvd3NfRXF1YWxfbW9kZSA9IGlmZWxzZShOX3Jvd3MgPT0gbW9kZS5OX3Jvd3MsIDEsIDApLAogICAgICAgICAgICAgICAgTl9yb3dzX05vdEVxdWFsX21vZGUgPSBpZmVsc2UoTl9yb3dzICE9IG1vZGUuTl9yb3dzLCAxLCAwKSkKICAgICAgIHByaW50KHBhc3RlKCJOID0gIiwgc3VtKHRlbXAkTl9yb3dzX0VxdWFsX21vZGUpLCAiIFJlY29yZElEcyB3aXRoIE5fcm93cyA9ICIsIHVuaXF1ZSh0ZW1wJG1vZGUuTl9yb3dzKSwgc2VwID0gIiIpKQogICAgICAgcHJpbnQocGFzdGUoIk4gPSAiLCBzdW0odGVtcCROX3Jvd3NfTm90RXF1YWxfbW9kZSksCiAgICAgICAgICAgICAgICAgICAiIFJlY29yZElEcyB3aXRoIG1lYW4gTl9yb3dzID0gIiwKICAgICAgICAgICAgICAgICAgIG1lYW4oKHRlbXAgJT4lIGZpbHRlcihOX3Jvd3MhPW1vZGUuTl9yb3dzKSkkTl9yb3dzKSwKICAgICAgICAgICAgICAgICAgICJcblByaW50aW5nIHByb2JsZW1hdGljIFJlY29yZElEcyBub3cuIFByb2JsZW1zIHN0b3JlZCBpbiBgcHJvYmxlbXNgIiwKICAgICAgICAgICAgICAgICAgIHNlcCA9ICIiKSkKICAgICAgICNwcmludChwYXN0ZSgiTiA9ICIsIHN1bSh0ZW1wJE5fRXF1YWxfbW9kZVsxXSksICIgc2FtcGxlcyB3aXRoIG5yb3cgPSAiLCB0ZW1wJE4sIHNlcCA9ICIiKSkKICAgICAgIAogICAgICAgcHJvYmxlbXMgPC0gdGVtcCAlPiUKICAgICAgICAgZmlsdGVyKE5fcm93cyAhPSBtb2RlLk5fcm93cykgJT4lCiAgICAgICAgIHNlbGVjdChSZWNvcmRJRCwgTl9yb3dzLCBtb2RlLk5fcm93cykgJT4lCiAgICAgICAgIGxlZnRfam9pbihtZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMiwgYnkgPSAiUmVjb3JkSUQiKSAlPiUKICAgICAgICAgc2VsZWN0KEZhbWlseUlELCBSZWNvcmRJRCwgTUVHQS5JSUQsIE1FR0EuTGFiSUQsIE5fcm93cywgbW9kZS5OX3Jvd3MpICU+JQogICAgICAgICB1bmlxdWUoKQogICAgICAgCiAgICAgICBwcmludChwcm9ibGVtcykKICAgICB9CmBgYAoKIyMjIyBJZiBhbGwgb2YgdGhlIGZvbGxvd2luZyBlcXVhbCB0aGUgc2FtZSBudW1iZXIgb2Ygcm93cywgdGhlbiB0aGlzIGRhdGFmcmFtZSBub3cgcmVwcmVzZW50cyBnZW5vdHlwaW5nIG9ubHkgb25jZSBwZXIgaW5kaXZpZHVhbApgYGB7cn0KbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDIgJT4lIGZpbHRlcihFWENMVURFX2Zyb21fYW5hbHlzaXMgPT0gMCkgJT4lCiAgc2VsZWN0KEZhbWlseUlELCBSZWNvcmRJRCwgTUVHQS5JSUQsIE1FR0EuTGFiSUQpICU+JQogIHVuaXF1ZSgpICU+JQogIG5yb3coKQoKbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDIgJT4lIGZpbHRlcihFWENMVURFX2Zyb21fYW5hbHlzaXMgPT0gMCkgJT4lCiAgc2VsZWN0KFJlY29yZElELCBNRUdBLklJRCwgTUVHQS5MYWJJRCkgJT4lCiAgdW5pcXVlKCkgJT4lCiAgbnJvdygpCgptZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMiAlPiUgZmlsdGVyKEVYQ0xVREVfZnJvbV9hbmFseXNpcyA9PSAwKSAlPiUKICBzZWxlY3QoTUVHQS5JSUQsIE1FR0EuTGFiSUQpICU+JQogIHVuaXF1ZSgpICU+JQogIG5yb3coKQoKbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDIgJT4lIGZpbHRlcihFWENMVURFX2Zyb21fYW5hbHlzaXMgPT0gMCkgJT4lCiAgc2VsZWN0KE1FR0EuTGFiSUQpICU+JQogIHVuaXF1ZSgpICU+JQogIG5yb3coKQoKbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDIgJT4lIGZpbHRlcihFWENMVURFX2Zyb21fYW5hbHlzaXMgPT0gMCkgJT4lCiAgc2VsZWN0KE1FR0EuSUlEKSAlPiUKICB1bmlxdWUoKSAlPiUKICBucm93KCkKCm1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAyICU+JSBmaWx0ZXIoRVhDTFVERV9mcm9tX2FuYWx5c2lzID09IDApICU+JQogIHNlbGVjdChSZWNvcmRJRCkgJT4lCiAgdW5pcXVlKCkgJT4lCiAgbnJvdygpCgptZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMiAlPiUgZmlsdGVyKEVYQ0xVREVfZnJvbV9hbmFseXNpcyA9PSAwKSAlPiUKICBzZWxlY3QoRmFtaWx5SUQsIFJlY29yZElELCBNRUdBLklJRCkgJT4lCiAgdW5pcXVlKCkgJT4lCiAgbnJvdygpCgptZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMiAlPiUgZmlsdGVyKEVYQ0xVREVfZnJvbV9hbmFseXNpcyA9PSAwKSAlPiUKICBzZWxlY3QoRmFtaWx5SUQsIFJlY29yZElEKSAlPiUKICB1bmlxdWUoKSAlPiUKICBucm93KCkKCm1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAyICU+JSBmaWx0ZXIoRVhDTFVERV9mcm9tX2FuYWx5c2lzID09IDApICU+JQogIHNlbGVjdChSZWNvcmRJRCwgTUVHQS5JSUQpICU+JQogIHVuaXF1ZSgpICU+JQogIG5yb3coKQoKcHJpbnQoIklmIGFsbCBvZiB0aGUgbnVtYmVycyBwcmludGVkIGFib3ZlIGVxdWFsIHRoZSBzYW1lIG51bWJlciBvZiByb3dzLCB0aGVuIHRoaXMgZGF0YWZyYW1lIG5vdyByZXByZXNlbnRzIGdlbm90eXBpbmcgb25seSBvbmNlIHBlciBpbmRpdmlkdWFsLiIpCnByaW50KCJHb29kLiIpCmBgYAoKIyMjIyBGaW5hbCBjaGVjayB0aGF0IGFsbCBSZWNvcmRJRHMgbm93IGhhdmUgb25seSAxIE1FR0EuSUlEIGFmdGVyIHVzaW5nIHRoZSBFWENMVURFX2Zyb21fYW5hbHlzaXMgY29sdW1uIHRvIGZpbHRlcgpgYGB7cn0KbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDIgJT4lIGZpbHRlcihFWENMVURFX2Zyb21fYW5hbHlzaXMgPT0gMCkgJT4lCiAgc2VsZWN0KFJlY29yZElELCBNRUdBLklJRCkgJT4lCiAgdW5pcXVlKCkgJT4lCiAgZ3JvdXBfYnkoUmVjb3JkSUQpICU+JQogIHN1bW1hcmlzZShOID0gbigpKSAlPiUKICBhcnJhbmdlKGRlc2MoTikpICU+JQogIGxlZnRfam9pbihtZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMiwgYnkgPSAiUmVjb3JkSUQiKSAlPiUKICBmaWx0ZXIoTiA+IDEpCgpwcmludCgiR29vZC4gQWxsIFJlY29yZElEcyBoYXZlIG9ubHkgMSBNRUdBLklJRCBhZnRlciBhcHBseWluZyB0aGUgRVhDTFVERV9mcm9tX2FuYWx5c2lzIGZpbHRlci4iKQpgYGAKCiMjIyMgQ2hlY2sgZm9yIHR3aW5zIGFuZCBvdGhlciByZWxhdGVkcwojIyMjIElmIHRoZXJlIGFyZSByZWxhdGVkcyBpbiB0aGUgZGF0YXNldCBhZnRlciBhcHBseWluZyB0aGUgRVhDTFVERSBmaWx0ZXIsIGZpcnN0IHByaW9yaXRpemUga2VlcGluZyBDZWxpYWMgY2FzZXMsIHRoZW4gcmFuZG9tbHkgY2hvb3NlIG9uZSBJSUQgcGVyIEZhbWlseUlEIHRvIHJldGFpbiBmb3IgYW5hbHlzaXMKYGBge3J9Cm1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAyICU+JSBmaWx0ZXIoRVhDTFVERV9mcm9tX2FuYWx5c2lzID09IDApICU+JQogIHNlbGVjdChGYW1pbHlJRCwgUmVjb3JkSUQpICU+JSAjLCBNRUdBLklJRCwgTUVHQS5MYWJJRCkgJT4lCiAgdW5pcXVlKCkgJT4lCiAgZ3JvdXBfYnkoRmFtaWx5SUQpICU+JQogIHN1bW1hcmlzZShOX1JlY29yZElEc19wZXJfRmFtaWx5SUQgPSBuKCkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBhcnJhbmdlKGRlc2MoTl9SZWNvcmRJRHNfcGVyX0ZhbWlseUlEKSkgJT4lCiAgZmlsdGVyKE5fUmVjb3JkSURzX3Blcl9GYW1pbHlJRCA+IDEpCgpyZWxhdGVkcyA8LSBtZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMiAlPiUgZmlsdGVyKEVYQ0xVREVfZnJvbV9hbmFseXNpcyA9PSAwKSAlPiUKICBzZWxlY3QoRmFtaWx5SUQsIFJlY29yZElEKSAlPiUgIywgTUVHQS5JSUQsIE1FR0EuTGFiSUQpICU+JQogIHVuaXF1ZSgpICU+JQogIGdyb3VwX2J5KEZhbWlseUlEKSAlPiUKICBzdW1tYXJpc2UoTl9SZWNvcmRJRHNfcGVyX0ZhbWlseUlEID0gbigpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgYXJyYW5nZShkZXNjKE5fUmVjb3JkSURzX3Blcl9GYW1pbHlJRCkpICU+JQogIGZpbHRlcihOX1JlY29yZElEc19wZXJfRmFtaWx5SUQgPiAxKSAlPiUKICBsZWZ0X2pvaW4obWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDIsIGJ5ID0gIkZhbWlseUlEIikgJT4lCiAgc2VsZWN0KEZhbWlseUlELCBOX1JlY29yZElEc19wZXJfRmFtaWx5SUQsIFJlY29yZElELCBNRUdBLklJRCwgTUVHQS5MYWJJRCwgRVhDTFVERV9mcm9tX2FuYWx5c2lzLCBDZWxpYWMsIFNleCwgQWdlX2F0X3Zpc2l0MSkgJT4lCiAgdW5pcXVlKCkgJT4lCiAgI2xlZnRfam9pbihtZXRhX2NvbW9yYi4wMjIwMjEsIGJ5ID0gYygiRmFtaWx5SUQiLCAiUmVjb3JkSUQiLCAiTUVHQS5MYWJJRCI9IkxhYklEIikpICU+JQogIGdyb3VwX2J5KEZhbWlseUlEKSAlPiUKICBhcnJhbmdlKGRlc2MoQ2VsaWFjKSkgJT4lCiAgbXV0YXRlKGluZGV4X3dpdGhpbl9GYW1pbHlJRCA9IHJvd19udW1iZXIoKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIHNlbGVjdChGYW1pbHlJRCwgTl9SZWNvcmRJRHNfcGVyX0ZhbWlseUlELCBpbmRleF93aXRoaW5fRmFtaWx5SUQsIENlbGlhYywgU2V4LCBBZ2VfYXRfdmlzaXQxLCBldmVyeXRoaW5nKCkpICU+JQogIGFycmFuZ2UoRmFtaWx5SUQsIGluZGV4X3dpdGhpbl9GYW1pbHlJRCkKCnJlbGF0ZWRzCgpyZWxhdGVkcyAlPiUKICBzZWxlY3QoRmFtaWx5SUQsIGluZGV4X3dpdGhpbl9GYW1pbHlJRCwgRVhDTFVERV9mcm9tX2FuYWx5c2lzLCBDZWxpYWMsIFNleCkgJT4lCiAgdW5pcXVlKCkgJT4lCiAgZ3JvdXBfYnkoRmFtaWx5SUQsIFNleCkgJT4lCiAgc3VtbWFyaXNlKE4gPSBuKCkpCgpwcmludCgiRGVjaXNpb246IEZyb20gRmFtaWx5SUQgRjAzNDggKDIgaW5kaXZpZHVhbHMpLCBrZWVwIElOVlRIMzI4SEE5IGJlY2F1c2UgdGhpcyBwZXJzb24gaXMgYSBDZWxpYWMgY2FzZS4iKQpwcmludCgiTm90ZTogQWxsIG90aGVyIGZhbWlseXMgaGF2ZSBvbmx5IG1hbGVzIG9yIG9ubHkgZmVtYWxlcywgZXhjZXB0IGZvciBvbmUgZmFtaWx5IHdpdGggMSBvZiBlYWNoLiIpCnByaW50KCJEZWNpc2lvbjogVGhlcmVmb3JlLCBmcm9tIGFsbCBvdGhlciBGYW1pbHlJRHMsIHJhbmRvbWx5IHNlbGVjdCBvbmUgaW5kaXZpZHVhbCB0byByZW1haW4gaW4gdGhlIGFuYWx5c2lzLiIpCgpzZXQuc2VlZCgxMjM0KSAjIFNldCBzZWVkIGZvciByYW5kb21seSBzaHVmZmxpbmcgcm93cwpyZWxhdGVkc190b19rZWVwID0gcmVsYXRlZHNbc2FtcGxlKDE6bnJvdyhyZWxhdGVkcykpLCBdICU+JQogIGdyb3VwX2J5KEZhbWlseUlEKSAlPiUKICBtdXRhdGUocmFuZG9tX2luZGV4ID0gcm93X251bWJlcigpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKEtlZXAgPSBpZmVsc2UoRmFtaWx5SUQgPT0gIkYwMzQ4IiAmIENlbGlhYyA9PSAxLCAxLAogICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShGYW1pbHlJRCA9PSAiRjAzNDgiICYgQ2VsaWFjID09IDAsIDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShyYW5kb21faW5kZXggPT0gMSwgMSwgMCkpKSkgJT4lCiAgc2VsZWN0KEZhbWlseUlELCBSZWNvcmRJRCwgTUVHQS5JSUQsIE1FR0EuTGFiSUQsIE5fUmVjb3JkSURzX3Blcl9GYW1pbHlJRCwgaW5kZXhfd2l0aGluX0ZhbWlseUlELCByYW5kb21faW5kZXgsIEtlZXAsIGV2ZXJ5dGhpbmcoKSkgJT4lCiAgYXJyYW5nZShGYW1pbHlJRCwgaW5kZXhfd2l0aGluX0ZhbWlseUlEKSAlPiUKICBmaWx0ZXIoS2VlcCA9PSAxKQpyZWxhdGVkc190b19rZWVwCnJlbGF0ZWRzX3RvX2tlZXAkTUVHQS5JSUQKYGBgCgojIyMjIFVwZGF0ZSB0aGUgYEVYQ0xVREVfZnJvbV9hbmFseXNpc2AgYW5kIGBFWENMVURFX3JlYXNvbmAgY29sdW1ucyB0byBpbmRpY2F0ZSB3aGljaCBJSURzIHRvIGV4Y2x1ZGUgd2l0aGluIG11bHRpcGxlLUlJRCBGYW1pbHlJRHMKYGBge3J9Cm1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAzIDwtIG1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAyICU+JQogIHNlbGVjdChGYW1pbHlJRCwgUmVjb3JkSUQpICU+JSAjLCBNRUdBLklJRCwgTUVHQS5MYWJJRCkgJT4lCiAgdW5pcXVlKCkgJT4lCiAgZ3JvdXBfYnkoRmFtaWx5SUQpICU+JQogIG11dGF0ZShOX1JlY29yZElEc19wZXJfRmFtaWx5SUQgPSBuKCkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBhcnJhbmdlKGRlc2MoTl9SZWNvcmRJRHNfcGVyX0ZhbWlseUlEKSkgJT4lCiAgbXV0YXRlKE11bHRpX0lJRF9GYW1pbHlJRCA9IGlmZWxzZShOX1JlY29yZElEc19wZXJfRmFtaWx5SUQgPiAxLCAxLCAwKSkgJT4lCiAgbGVmdF9qb2luKG1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAyLCBieSA9IGMoIkZhbWlseUlEIiwgIlJlY29yZElEIikpICU+JQogIG11dGF0ZShLZWVwX2Zyb21fTXVsdGlfSUlEX0ZhbWlseUlEID0gaWZlbHNlKE1FR0EuSUlEICVpbiUgcmVsYXRlZHNfdG9fa2VlcCRNRUdBLklJRCwgMSwgMCkpICU+JQogIG11dGF0ZShFWENMVURFX3JlYXNvbiA9IGdzdWIoIlsuXSIsICIiLCBFWENMVURFX3JlYXNvbikpICU+JQogICNmaWx0ZXIoTXVsdGlfSUlEX0ZhbWlseUlEPT0xKSAlPiUgc2VsZWN0KEZhbWlseUlELCBSZWNvcmRJRCwgTl9SZWNvcmRJRHNfcGVyX0ZhbWlseUlELCBNRUdBLklJRCwgS2VlcF9mcm9tX011bHRpX0lJRF9GYW1pbHlJRCkgJT4lIHVuaXF1ZSgpICU+JSBhcnJhbmdlKEZhbWlseUlELCBkZXNjKEtlZXBfZnJvbV9NdWx0aV9JSURfRmFtaWx5SUQpKQogIG11dGF0ZShFWENMVURFX2Zyb21fYW5hbHlzaXMgPSBpZmVsc2UoTXVsdGlfSUlEX0ZhbWlseUlEID09IDEgJiBLZWVwX2Zyb21fTXVsdGlfSUlEX0ZhbWlseUlEID09IDAsIDEsIEVYQ0xVREVfZnJvbV9hbmFseXNpcyksCiAgICAgICAgIEVYQ0xVREVfcmVhc29uID0gaWZlbHNlKGlzLm5hKEVYQ0xVREVfcmVhc29uKSAmIE11bHRpX0lJRF9GYW1pbHlJRCA9PSAxICYgRVhDTFVERV9mcm9tX2FuYWx5c2lzID09IDEsICJGYW1pbHlJRCB3aXRoIG11bHRpcGxlIFJlY29yZElEcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSghaXMubmEoRVhDTFVERV9yZWFzb24pICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE11bHRpX0lJRF9GYW1pbHlJRCA9PSAxICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVhDTFVERV9mcm9tX2FuYWx5c2lzID09IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZShFWENMVURFX3JlYXNvbiwgIjsgRmFtaWx5SUQgd2l0aCBtdWx0aXBsZSBSZWNvcmRJRHMiLCBzZXAgPSAiIiksIEVYQ0xVREVfcmVhc29uKSkpICU+JQogIHNlbGVjdCgtYyhLZWVwX2Zyb21fTXVsdGlfSUlEX0ZhbWlseUlEKSkgJT4lCiAgcmVuYW1lKE5fVDIxX1JlY29yZElEc19pbl9GYW1pbHlJRCA9IE5fUmVjb3JkSURzX3Blcl9GYW1pbHlJRCkgJT4lCiAgc2VsZWN0KEZhbWlseUlELCBSZWNvcmRJRCwgTUVHQS5GSUQsIE1FR0EuSUlELCBNRUdBLkxhYklELCBNdWx0aV9JSURfRmFtaWx5SUQsIE5fVDIxX1JlY29yZElEc19pbl9GYW1pbHlJRCwgZXZlcnl0aGluZygpKSAjJT4lCiAgI211dGF0ZShFWENMVURFX2Zyb21fYW5hbHlzaXMgPSBpZmVsc2UoaXMubmEoRVhDTFVERV9mcm9tX2FuYWx5c2lzKSwgMCwgRVhDTFVERV9mcm9tX2FuYWx5c2lzKSkKCm1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAzCgptZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMyAlPiUKICBzZWxlY3QoRmFtaWx5SUQsIFJlY29yZElELCBNRUdBLkZJRCwgTUVHQS5JSUQsIE1FR0EuTGFiSUQsCiAgICAgICAgIE11bHRpX0lJRF9GYW1pbHlJRCwgTl9UMjFfUmVjb3JkSURzX2luX0ZhbWlseUlELCBDZWxpYWMsIEVYQ0xVREVfZnJvbV9hbmFseXNpcywgRVhDTFVERV9yZWFzb24pICU+JQogIHVuaXF1ZSgpICU+JQogIGFycmFuZ2UoZGVzYyhDZWxpYWMpLCBkZXNjKEVYQ0xVREVfZnJvbV9hbmFseXNpcykpCmBgYAoKIyMjIyBWZXJpZnkgdGhhdCB0aGUgRVhDTFVERSB2YXJpYWJsZSBpcyB3b3JraW5nIGNvcnJlY3RseQpOb3QgZXhjbHVkaW5nIGFueSBDZWxpYWMgY2FzZXMgdW5sZXNzIHRoZXkgcmVwcmVzZW50IGEgUmVjb3JkSUQgZ2Vub3R5cGVkIHR3aWNlIG9uIE1FR0EuClByb2R1Y2luZyBhIGRhdGFzZXQgd2l0aCBvbmx5IG9uZSBNRUdBLklJRCBwZXIgUmVjb3JkSUQuClByb2R1Y2luZyBhIGRhdGFzZXQgd2l0aCBvbmx5IG9uZSBSZWNvcmRJRCBwZXIgRmFtaWx5SUQuCmBgYHtyfQptZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMyAlPiUKICBzZWxlY3QoTUVHQS5JSUQsIE1FR0EuTGFiSUQsIENlbGlhYywgRVhDTFVERV9mcm9tX2FuYWx5c2lzLCBFWENMVURFX3JlYXNvbikgJT4lCiAgdW5pcXVlKCkgJT4lCiAgZ3JvdXBfYnkoQ2VsaWFjLCBFWENMVURFX2Zyb21fYW5hbHlzaXMsIEVYQ0xVREVfcmVhc29uKSAlPiUKICBzdW1tYXJpc2UoTiA9IG4oKSkKcHJpbnQoIkdvb2QsIG5vdCBleGNsdWRpbmcgYW55IENlbGlhYyBjYXNlcyB1bmxlc3MgdGhleSByZXByZXNlbnQgYSBSZWNvcmRJRCBnZW5vdHlwZWQgdHdpY2Ugb24gTUVHQS4iKQpwcmludCgiUmVhc29ucyB3ZSBhcmUgY3VycmVudGx5IGV4Y2x1ZGluZyBJSURzIHJlcHJlc2VudGVkIGluIHRoZSBwbGluayAqLmZhbSBhcmU6CiAgICAgIDEpIElmIHRoZSBJSUQgaXMgZm9yIGEgUmVjb3JkSUQgdGhhdCBnb3QgZ2Vub3R5cGVkIHR3aWNlLCBvcgogICAgICAyKSBJZiB0aGUgSUlEIGlzIGZyb20gYSBGYW1pbHlJRCB3aXRoIG11bHRpcGxlIGdlbm90eXBlZCBpbmRpdmlkdWFscy4iKQoKbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDMgJT4lCiAgZmlsdGVyKEVYQ0xVREVfZnJvbV9hbmFseXNpcyA9PSAwKSAlPiUKICBzZWxlY3QoUmVjb3JkSUQsIE1FR0EuSUlEKSAlPiUKICB1bmlxdWUoKSAlPiUKICBncm91cF9ieShSZWNvcmRJRCkgJT4lCiAgc3VtbWFyaXNlKE4gPSBuKCkpICU+JQogIGFycmFuZ2UoZGVzYyhOKSkKcHJpbnQoIkdvb2QsIG9ubHkgb25lIE1FR0EuSUlEIHBlciBSZWNvcmRJRC4iKQoKbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDMgJT4lCiAgI2ZpbHRlcihFWENMVURFX2Zyb21fYW5hbHlzaXMgPT0gMCkgJT4lCiAgc2VsZWN0KEZhbWlseUlELCBSZWNvcmRJRCwgTUVHQS5JSUQpICU+JQogIHVuaXF1ZSgpICU+JQogIGdyb3VwX2J5KEZhbWlseUlELCBSZWNvcmRJRCwgTUVHQS5JSUQpICU+JQogIHN1bW1hcmlzZShOID0gbigpKSAlPiUKICBhcnJhbmdlKGRlc2MoTikpCnByaW50KCJHb29kLCBvbmx5IG9uZSBSZWNvcmRJRCBwZXIgRmFtaWx5SUQuIikKYGBgCgojIyMjIFZpZXcgd2hvIGlzIGJlaW5nIGV4Y2x1ZGVkIGF0IHRoaXMgc3RhZ2UgYW5kIHdoeQpgYGB7cn0KbWV0YS5NRUdBLlQyMV92aXNpdDFfQ2VsaWFjMDMgJT4lCiAgc2VsZWN0KEZhbWlseUlELCBSZWNvcmRJRCwgTUVHQS5GSUQsIE1FR0EuSUlELCBNRUdBLkxhYklELCBDZWxpYWMsIEVYQ0xVREVfZnJvbV9hbmFseXNpcywgRVhDTFVERV9yZWFzb24pICU+JQogIHVuaXF1ZSgpICU+JQogIGdyb3VwX2J5KEVYQ0xVREVfZnJvbV9hbmFseXNpcywgRVhDTFVERV9yZWFzb24sIENlbGlhYykgJT4lCiAgc3VtbWFyaXNlKE4gPSBuKCkpCgptZXRhLk1FR0EuVDIxX3Zpc2l0MV9DZWxpYWMwMyAlPiUKICBzZWxlY3QoRmFtaWx5SUQsIFJlY29yZElELCBNRUdBLkZJRCwgTUVHQS5JSUQsIE1FR0EuTGFiSUQsIEVYQ0xVREVfZnJvbV9hbmFseXNpcywgRVhDTFVERV9yZWFzb24sIEthcnlvdHlwZSwgQ2VsaWFjLCBTZXgpICU+JQogIHVuaXF1ZSgpICU+JQogIGdyb3VwX2J5KEVYQ0xVREVfZnJvbV9hbmFseXNpcywgRVhDTFVERV9yZWFzb24sIEthcnlvdHlwZSwgQ2VsaWFjLCBTZXgpICU+JQogIHN1bW1hcmlzZShOID0gbigpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgI2ZpbHRlcigjRVhDTFVERV9mcm9tX2FuYWx5c2lzID09IDAgJgogICMgICAgICAgICAhaXMubmEoQ2VsaWFjKSkgJT4lCiAgbXV0YXRlKFRvdGFsID0gc3VtKE4pLAogICAgICAgICBQY3QgPSByb3VuZCgxMDAqTi9Ub3RhbCwgZGlnaXRzID0gMikpICU+JQogIG11dGF0ZShgTiAoJSlgID0gcGFzdGUoTiwgIiAoIiwgUGN0LCAiKSIsIHNlcCA9ICIiKSkgJT4lCiAgc2VsZWN0KEVYQ0xVREVfZnJvbV9hbmFseXNpcywgRVhDTFVERV9yZWFzb24sIEthcnlvdHlwZSwgQ2VsaWFjLCBTZXgsIGBOICglKWApICU+JQogIG11dGF0ZShHcm91cCA9IGlmZWxzZShDZWxpYWMgPT0gMCwgIlQyMSB3aXRob3V0IENEIiwKICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKENlbGlhYyA9PSAxLCAiVDIxIHdpdGggQ0QiLCBOQSkpKSAlPiUKICBzZWxlY3QoRVhDTFVERV9mcm9tX2FuYWx5c2lzLCBFWENMVURFX3JlYXNvbiwgR3JvdXAsIFNleCwgYE4gKCUpYCkKYGBgCgojIyMjIFNhdmUgdG8gZmlsZXMKYGBge3J9CnNldHdkKGRpcikKZndyaXRlKG1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAzLCAiTUVHQV8wNDE4MjJfTUVUQV9DZWxpYWNHUlNfdjAuMV9KUlMuY3N2IikKZndyaXRlKG1ldGEuTUVHQS5UMjFfdmlzaXQxX0NlbGlhYzAzLCAiTUVHQV8wNDE4MjJfTUVUQV9DZWxpYWNHUlNfdjAuMV9KUlMudHN2Iiwgc2VwID0gIlx0IikKYGBgCg==